/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zh.harmony.lifecycle;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilityLifecycleCallbacks;
import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.ability.fraction.FractionAbility;
import ohos.aafwk.content.Intent;
import ohos.utils.PacMap;

import java.lang.ref.WeakReference;

/**
 * 获取事件的透明Fragment
 */
@SuppressWarnings("UnknownNullness") // TODO https://issuetracker.google.com/issues/112197238
public class ReportFragment extends Fraction {
    private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";

    /**
     * 插入一个透明Fragment到Activity中获取事件
     */
    public static void injectIfNeededIn(Ability activity) {
        //通过AbilityPackage注册生命周期回调来解决，注意这个回调是所有Ability改变时都会回调的
        //原版Android上，使用的是activity.registerActivityLifecycleCallbacks()，这个是只针对目标activity的，并且API是29以上才有，就是安卓10以上
        //但鸿蒙上没有这个API，所以只能在LifecycleCallbacks中，判断回调的是不是目标ability
        activity.getAbilityPackage().registerCallbacks(new LifecycleCallbacks(activity), null);

        // ProcessLifecycleOwner should always correctly work and some activities may not extend
        // FragmentActivity from support lib, so we use framework fragments for activities
        //鸿蒙的Fraction有缺陷，必须指定容器Id，而且内存重启后，实例就销毁了，无法getFractionByTag()查找回来，同时框架会自动创建一个新的实例添加进来，又不可以干预

//        FractionManager manager = activity.getFractionManager();
//        if (!manager.getFractionByTag(REPORT_FRAGMENT_TAG).isPresent()) {
//            FractionScheduler scheduler = manager.startFractionScheduler().add(0, new ReportFragment(), REPORT_FRAGMENT_TAG);
//            // Hopefully, we are the first to make a transaction.
//            scheduler.submit();
//        }
    }

    /**
     * 获取Activity上的ReportFragment实例，如果没有则返回null
     */
    public static ReportFragment get(FractionAbility activity) {
        return (ReportFragment) activity.getFractionManager().getFractionByTag(
                REPORT_FRAGMENT_TAG).orElse(null);
    }

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        //onCreate()
        dispatch(Lifecycle.Event.ON_CREATE);
        //onStart()
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    protected void onActive() {
        super.onActive();
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    protected void onBackground() {
        super.onBackground();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_DESTROY);
    }

    private void dispatch(Lifecycle.Event event) {
        dispatch(getFractionAbility(), event);
    }

    /**
     * 分发事件给观察者
     */
    static void dispatch(Ability activity, Lifecycle.Event event) {
        //先判断有没有实现LifecycleRegistryOwner接口，有则交给它分发
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifeCycle().handleLifecycleEvent(event);
            return;
        }
        //没有实现LifecycleRegistryOwner接口，但实现LifecycleOwner接口，则交给它分发
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifeCycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

    // this class isn't inlined only because we need to add a proguard rule for it. (b/142778206)
    static class LifecycleCallbacks implements AbilityLifecycleCallbacks {
        private WeakReference<Ability> mTargetAbility;

        public LifecycleCallbacks(Ability ability) {
            this.mTargetAbility = new WeakReference<>(ability);
        }

        @Override
        public void onAbilityStart(Ability ability) {
            if (mTargetAbility == null || mTargetAbility.get() == null) {
                return;
            }
            if (mTargetAbility.get() != ability) {
                return;
            }
            dispatch(ability, Lifecycle.Event.ON_CREATE);
        }

        @Override
        public void onAbilityActive(Ability ability) {
            if (mTargetAbility == null || mTargetAbility.get() == null) {
                return;
            }
            if (mTargetAbility.get() != ability) {
                return;
            }
            dispatch(ability, Lifecycle.Event.ON_START);
        }

        @Override
        public void onAbilityForeground(Ability ability) {
            if (mTargetAbility == null || mTargetAbility.get() == null) {
                return;
            }
            if (mTargetAbility.get() != ability) {
                return;
            }
            dispatch(ability, Lifecycle.Event.ON_RESUME);
        }

        @Override
        public void onAbilityInactive(Ability ability) {
            if (mTargetAbility == null || mTargetAbility.get() == null) {
                return;
            }
            if (mTargetAbility.get() != ability) {
                return;
            }
            dispatch(ability, Lifecycle.Event.ON_PAUSE);
        }

        @Override
        public void onAbilityBackground(Ability ability) {
            if (mTargetAbility == null || mTargetAbility.get() == null) {
                return;
            }
            if (mTargetAbility.get() != ability) {
                return;
            }
            dispatch(ability, Lifecycle.Event.ON_STOP);
        }

        @Override
        public void onAbilityStop(Ability ability) {
            if (mTargetAbility == null || mTargetAbility.get() == null) {
                return;
            }
            if (mTargetAbility.get() != ability) {
                return;
            }
            dispatch(ability, Lifecycle.Event.ON_DESTROY);
            mTargetAbility.get().getAbilityPackage().unregisterCallbacks(this, null);
            mTargetAbility.clear();
            mTargetAbility = null;
        }

        @Override
        public void onAbilitySaveState(PacMap pacMap) {
        }
    }
}